package archive;

import java.util.Vector;

import neuralnetworks.NeuralNetwork;



public class SequencedExampleSet
{
    Vector<Example> d_examples;
    int d_inputsize;
    int d_outputsize;
    
    public SequencedExampleSet()
    {
        
    }
    
    public SequencedExampleSet(Vector<Example> examples)
    {
        if(examples.size() > 0)
        d_examples   = examples;
        d_inputsize  = d_examples.get(0).d_input.length;
        d_outputsize = d_examples.get(0).d_target.length;
    }
    
    public SequencedExampleSet(Example example)
    {
        d_examples = new Vector<Example>();
        d_examples.add(example);
        d_inputsize  = d_examples.get(0).d_input.length;
        d_outputsize = d_examples.get(0).d_target.length;
    }
    
    public void append(Example example)
    {
        if (d_examples == null)
        {
            d_examples = new Vector<Example>();
            d_examples.add(example);
            d_inputsize  = d_examples.get(0).d_input.length;
            d_outputsize = d_examples.get(0).d_target.length;
        }
        else
        {
            if(d_examples.get(0).match(example))
                d_examples.add(example);
            else
                System.out.println("Error: incompatible data. Example not added");
        }
    }
    
    public void append(Vector<Example> examples)
    {
        if (d_examples == null)
        {
            d_examples = new Vector<Example>(examples);
            d_inputsize  = d_examples.get(0).d_input.length;
            d_outputsize = d_examples.get(0).d_target.length;
        }
        else
        {
            if(d_examples.get(0).match(examples.get(0)))
                d_examples.addAll(examples);
            else
                System.out.println("Error: incompatible data. Example not added");
        }
    }
    
    private boolean checkCompatible(NeuralNetwork network)
    {
        if(d_inputsize != network.getInputLayerSize())
            return false;
        if(d_outputsize != network.getOutputLayerSize())
            return false;
        return true;
    }
    
    public double getSummedError(NeuralNetwork network)
    {
        if(!checkCompatible(network))
        {
            System.out.println("Error: incompatible network. Examples not tested");
            return -1;
        }
        double error = 0;
        for(int index = 0; index < d_examples.size(); ++index)
            error += getAbsoluteSummedError(network, d_examples.get(index));
        return error;
    }
    
//    public void teachBySequence(NeuralNetwork network, int amount)
//    {
//        for(int iteration = 0; iteration < amount; ++iteration)
//        {
//            System.out.println("Learing: percentage done: " + (((double)iteration/(double)amount) * 100) + "%");
//            for(int index = 0; index < d_examples.size(); ++index)
//                network.train(d_examples.get(index));
//
//        }
//        System.out.println("Learing: Percentage done: 100%");
//    }
    
    public static double absoluteSum(double [] array)
    {
        double sum = 0;
        for(double element: array)
            sum += Math.abs(element);
        return sum;
    }
    
    
    private static double getAbsoluteSummedError(NeuralNetwork network, Example example)
    {
        return absoluteSum(getError(network, example));
    }
    
    private static double [] getError(NeuralNetwork network, Example example)
    {
        double [] output = network.process(example.d_input);
        return substract(example.d_target,output);
    }
    
    public static double [] substract(double [] array1, double [] array2) // pre-allocate result?
    {
        if(array1.length != array2.length)
            return null;
        double [] result = new double [array1.length];
        for(int index = 0; index < array1.length; ++index)
            result[index] = array1[index] - array2[index];
        return result;
    }
}
